package com.yeyks.commonReference.append.activity.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.WeightRandom;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.yeyks.activity.dal.domain.ActivityDrawRecordNew;
import com.yeyks.activity.dal.domain.ActivityList;
import com.yeyks.activity.dal.domain.ActivityNodeUserRecord;
import com.yeyks.activity.dal.domain.ActivityPrizeInfo;
import com.yeyks.activity.service.ActivityNodeUserRecordService;
import com.yeyks.activity.service.ActivityPrizeInfoService;
import com.yeyks.activity.service.ActivityUserJoinRecordService;
import com.yeyks.common.constants.activity.ActivityPrizeInfoTypeConstant;
import com.yeyks.common.constants.activity.RedisKeyPreConstant;
import com.yeyks.common.dto.DoubleDanConfig;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.PageParam;
import com.yeyks.common.param.consumer.UserIdParam;
import com.yeyks.common.result.activity.*;
import com.yeyks.common.utils.RedisUtil;
import com.yeyks.commonReference.append.activity.ActivityDoubleDanService;
import com.yeyks.commonReference.append.statistic.StatisticBaseService;
import com.yeyks.commonReference.pojo.param.activity.DoubleDan.*;
import com.yeyks.commonReference.pojo.vo.activity.DoubleDan.*;
import com.yeyks.commonReference.service.activity.ActivityBaseService;
import com.yeyks.commonReference.service.config.ConfigService;
import com.yeyks.consumer.dal.domain.UserInviteRelation;
import com.yeyks.consumer.service.UserInviteRelationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class ActivityDoubleDanServiceImpl implements ActivityDoubleDanService {

    private static final String DOUBLE_DAN = "DoubleDan";
    //转发记录
    private static final String DOUBLE_DAN_AFNR = DOUBLE_DAN + "AFNR";

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ActivityBaseService activityBaseService;
    @Autowired
    private StatisticBaseService statisticBaseService;
    @Autowired
    private ActivityPrizeInfoService activityPrizeInfoService;
    @Autowired
    private ActivityUserJoinRecordService activityUserJoinRecordService;
    @Autowired
    private ActivityNodeUserRecordService activityNodeUserRecordService;
    @Autowired
    private UserInviteRelationService userInviteRelationService;
    @Autowired
    private ConfigService configService;

    //获取活动信息
    @Override
    public ActivityList getActivityDetail() {
        ActivityList activityList = activityBaseService.getActivityDetail(DOUBLE_DAN);
        activityList.setCreateTime(null).setUpdateTime(null).setOperatorId(null);
        return activityList;
    }

    //统计活动
    @Override
    public boolean statisticIncrement(ActivityDoubleDanStatisticIncrementParam param) {
        return statisticBaseService.statisticIncrement(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, param.getKey());
    }

    //活动转发人数记录
    @Override
    public void statisticIncrementActivityForwardNumberRecord(ActivityDoubleDanStatisticIncrementActivityForwardNumberRecordParam param) {
        try {
            ActivityNodeUserRecord activityNodeUserRecord = new ActivityNodeUserRecord();
            activityNodeUserRecord.setActivityCode(DOUBLE_DAN_AFNR);
            activityNodeUserRecord.setNode(String.valueOf(param.getSource()));
            activityNodeUserRecord.setUserId(param.getUserId());
            activityNodeUserRecordService.save(activityNodeUserRecord);
        } catch (Exception e) {
        }
        try {
            switch (param.getSource()) {
                case 1:
                    statisticIncrement(new ActivityDoubleDanStatisticIncrementParam().setKey("AFC"));
                    break;
                case 2:
                    statisticIncrement(new ActivityDoubleDanStatisticIncrementParam().setKey("ARA"));
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //轮播
    @Override
    public List<ActivityDoubleDanGetCarouselVo> getCarousel(PageParam param) {
        return activityBaseService.getCarousel(DOUBLE_DAN, param);
    }

    //获取宝箱状况
    @Override
    public ActivityDoubleDanTreasureChestStatusVo getTreasureChestStatus(ActivityDoubleDanTreasureChestStatusParam param) {
        //参加人数
        int participationCount = activityBaseService.getParticipationCount(DOUBLE_DAN);
        //当前用户抽过的宝箱
        List<ActivityNodeUserRecord> activityNodeJoinList = activityBaseService.getActivityNodeJoinList(DOUBLE_DAN, param.getUserId());
        ArrayList<String> strList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(activityNodeJoinList)) {
            for (ActivityNodeUserRecord activityNodeUserRecord : activityNodeJoinList) {
                strList.add(activityNodeUserRecord.getNode());
            }
        }
        //判断是否可以参与抽宝箱
        boolean determineIfYouCanDrawATreasureChest = determineIfYouCanDrawATreasureChest(param.getUserId());
        //生成返回值
        HashMap<String, Integer> map = new HashMap<>();
        Integer lotteryTreasureChestLevel = getLotteryTreasureChestLevel(participationCount);
        for (Integer node : ActivityDoubleDanServiceImpl.lotteryTreasureChestLevel) {
            if (Objects.equals(lotteryTreasureChestLevel, node)) {
                if (determineIfYouCanDrawATreasureChest) {
                    if (strList.contains(String.valueOf(node))) {
                        map.put(String.valueOf(node), 4);
                        continue;
                    } else {
                        map.put(String.valueOf(node), 3);
                        continue;
                    }
                } else {
                    map.put(String.valueOf(node), 1);
                }
            } else if (node < lotteryTreasureChestLevel) {
                if (strList.contains(String.valueOf(node))) {
                    map.put(String.valueOf(node), 2);
                    continue;
                } else {
                    map.put(String.valueOf(node), 1);
                    continue;
                }
            } else {
                map.put(String.valueOf(node), 5);
                continue;
            }
        }
        return new ActivityDoubleDanTreasureChestStatusVo().setCount(participationCount).setMap(map);
    }

    //宝箱红包概率
    private static final WeightRandom<Integer> lotteryTreasureChestWeightRandom = new WeightRandom<>(
            new WeightRandom.WeightObj[]{
                    new WeightRandom.WeightObj<>(10, 60.00),
                    new WeightRandom.WeightObj<>(20, 25.00),
                    new WeightRandom.WeightObj<>(30, 10.00),
                    new WeightRandom.WeightObj<>(40, 2.00),
                    new WeightRandom.WeightObj<>(50, 0.50),
                    new WeightRandom.WeightObj<>(60, 0.50),
                    new WeightRandom.WeightObj<>(70, 0.50),
                    new WeightRandom.WeightObj<>(80, 0.50),
                    new WeightRandom.WeightObj<>(90, 0.50),
                    new WeightRandom.WeightObj<>(100, 0.50)
            }
    );

    //宝箱阶段
    private static final Integer[] lotteryTreasureChestLevel = new Integer[]{30000, 20000, 10000, 5000, 2000};

    //根据人数获取宝箱阶段
    private Integer getLotteryTreasureChestLevel(Integer count) {
        for (Integer integer : lotteryTreasureChestLevel) {
            if (count > integer) {
                return integer;
            }
        }
        return 0;
    }

    //判断是否可以抽宝箱
    private boolean determineIfYouCanDrawATreasureChest(Integer userId) {
        return userInviteRelationService.count(
                new QueryWrapper<UserInviteRelation>()
                        .eq(UserInviteRelation.PARENT_ID, userId)
                        .eq(UserInviteRelation.TYPE, 4)
        ) > 0;
    }

    //抽保险锁
    private static final String lotteryTreasureChestLock = RedisKeyPreConstant.LOCK_ACTIVITY_DO_PRE + DOUBLE_DAN + ":lotteryTreasureChestLock:";

    //抽宝箱
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ActivityDoubleDanlotteryTreasureChestVo lotteryTreasureChest(ActivityDoubleDanlotteryTreasureChestParam param) {
        //参与人数
        int participationCount = activityBaseService.getParticipationCount(DOUBLE_DAN);
        //抽奖阶段
        Integer lotteryTreasureChestLevel = getLotteryTreasureChestLevel(participationCount);
        //子活动code
        if (lotteryTreasureChestLevel > 0) {
            //判断是否可以参与抽宝箱
            boolean determineIfYouCanDrawATreasureChest = determineIfYouCanDrawATreasureChest(param.getUserId());
            if (!determineIfYouCanDrawATreasureChest) {
                throw new ServiceException("您没有抽奖资格！");
            }
            //判断是否抽奖
            return redisUtil.runWithLock(lotteryTreasureChestLock + param.getUserId(), () -> {
                //判断是否抽过奖
                ActivityNodeUserRecord activityNodeUserRecord = activityNodeUserRecordService.getOne(
                        new QueryWrapper<ActivityNodeUserRecord>()
                                .eq(ActivityNodeUserRecord.USER_ID, param.getUserId())
                                .eq(ActivityNodeUserRecord.ACTIVITY_CODE, DOUBLE_DAN)
                                .eq(ActivityNodeUserRecord.NODE, String.valueOf(lotteryTreasureChestLevel))
                                .last("limit 1")
                );
                if (Objects.isNull(activityNodeUserRecord)) {
                    Integer amount = lotteryTreasureChestWeightRandom.next();
                    //发红包
                    activityBaseService.sendRedEnvelope(amount, DOUBLE_DAN, param.getUserId());
                    //存抽奖记录
                    activityNodeUserRecord = new ActivityNodeUserRecord();
                    activityNodeUserRecord.setUserId(param.getUserId()).setActivityCode(DOUBLE_DAN).setNode(String.valueOf(lotteryTreasureChestLevel));
                    activityNodeUserRecordService.save(activityNodeUserRecord);
                    return new ActivityDoubleDanlotteryTreasureChestVo().setPrizePrice(amount);
                }
                throw new ServiceException("您已参与过该次抽奖！");
            });
        }
        throw new ServiceException("您已参与过该次抽奖！");
    }

    //获取奖品列表
    @Override
    public ActivityDoubleDanGetPrizeListVo getPrizeList() {
        //检查活动是否结束
        activityBaseService.checkActivityEndDate(DOUBLE_DAN);
        //查询列表
        List<ActivityPrizeInfo> activityPrizeInfoList = activityBaseService.getActivityPrizeInfoList(DOUBLE_DAN);
        //封装返回值
        ArrayList<ActivityDoubleDanGetPrizeListVoPrize> activityDoubleDanGetPrizeListVoPrizes = new ArrayList<>();
        for (ActivityPrizeInfo activityPrizeInfo : activityPrizeInfoList) {
            ActivityDoubleDanGetPrizeListVoPrize activityDoubleDanGetPrizeListVoPrize = new ActivityDoubleDanGetPrizeListVoPrize()
                    .setId(activityPrizeInfo.getId())
                    .setPrizeImageUrl(activityPrizeInfo.getPrizeImageUrl());
            activityDoubleDanGetPrizeListVoPrizes.add(activityDoubleDanGetPrizeListVoPrize);
        }
        return new ActivityDoubleDanGetPrizeListVo().setList(activityDoubleDanGetPrizeListVoPrizes);
    }

    //获取抽奖次数
    @Override
    public ActivityDoubleDanGetPrizeCountVo getPrizeCount(UserIdParam param) {
        //检查活动是否结束
        activityBaseService.checkActivityEndDate(DOUBLE_DAN);
        //生成返回对象
        ActivityDoubleDanGetPrizeCountVo vo = new ActivityDoubleDanGetPrizeCountVo();
        //获取抽奖次数
        Integer lotteryCount = getLotteryCount(param.getUserId());
        vo.setRemainingTimes(lotteryCount);
        return vo;
    }

    //抽奖
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ActivityDoubleDanLotteryVo lottery(ActivityDoubleDanLotteryParam param) {
        //检查活动是否结束
        activityBaseService.checkActivityEndDate(DOUBLE_DAN);
        //记录并判断是否是第一次抽奖
        boolean isFistLottery = activityBaseService.recordParticipation(DOUBLE_DAN, param.getUserId());
        //生成返回对象
        ActivityDoubleDanLotteryVo activityDoubleDanLotteryVo = new ActivityDoubleDanLotteryVo();
        HashOperations<String, String, Integer> hashOperations = redisTemplate.opsForHash();
        //获取抽奖次数
        Integer lotteryCount = getLotteryCount(param.getUserId());
        if (CompareUtil.compare(lotteryCount, 0) > 0) {
            activityDoubleDanLotteryVo.setEnable(true);
            activityDoubleDanLotteryVo.setRemainingTimes(lotteryCount - 1);
            //判断用户是否是该活动注册用户
            boolean isThisActivityRegisteredUser = Objects.nonNull(
                    userInviteRelationService.getOne(
                            new QueryWrapper<UserInviteRelation>()
                                    .eq(UserInviteRelation.TYPE, 4)
                                    .eq(UserInviteRelation.USER_ID, param.getUserId())
                                    .last("limit 1")
                    )
            );
            //增加推广人可抽奖的次数，不是自己，是活动注册用户，是第一次抽奖
            if (!Objects.equals(param.getUserId(), param.getParentId()) && isThisActivityRegisteredUser && isFistLottery) {
                inrLotteryCount(param.getParentId(), 2);
            }
            //增加已抽奖次数
            hashOperations.increment(getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_COUNT), String.valueOf(param.getUserId()), 1);
            //获取抽奖权重并抽奖
            WeightRandom<ActivityPrizeInfo> weightRandom;
            if (isFistLottery && isThisActivityRegisteredUser) {
                //第一次抽奖
                lotteryFist(param, activityDoubleDanLotteryVo);
            } else {
                weightRandom = activityBaseService.getWeightRandom(DOUBLE_DAN, 1);
                ActivityPrizeInfo activityPrizeInfo_1 = weightRandom.next();
                ActivityPrizeInfo activityPrizeInfo_2 = null;
                //如果有二级奖品,二次抽奖
                if (Objects.equals(activityPrizeInfo_1.getWhetherAppend(), 1)) {
                    weightRandom = activityBaseService.getWeightRandom(DOUBLE_DAN, 2, activityPrizeInfo_1.getId());
                    activityPrizeInfo_2 = weightRandom.next();
                }
                if (Objects.isNull(activityPrizeInfo_2)) {
                    activityPrizeInfo_2 = activityPrizeInfo_1;
                }
                //发放奖品
                boolean giveAwayPrizesSuccess = activityBaseService.giveAwayPrizes(DOUBLE_DAN, activityPrizeInfo_2.getId(), param.getUserId());
                //封装返回值数据
                if (giveAwayPrizesSuccess) {
                    activityDoubleDanLotteryVo.setPrizeId(activityPrizeInfo_1.getId());
                    activityDoubleDanLotteryVo.setPrizeName(activityPrizeInfo_2.getPrizeName());
                    activityDoubleDanLotteryVo.setPrizeType(activityPrizeInfo_2.getPrizeType());
                    activityDoubleDanLotteryVo.setPrizeImageReturnUrl(activityPrizeInfo_2.getPrizeImageReturnUrl());
                    activityDoubleDanLotteryVo.setPrizePrice(activityPrizeInfo_2.getPrizePrice());
                    activityDoubleDanLotteryVo.setEndTime(activityPrizeInfo_2.getEndTime());
                } else {
                    ActivityPrizeInfo activityPrizeInfo = activityPrizeInfoService.getOne(
                            new QueryWrapper<ActivityPrizeInfo>()
                                    .eq(ActivityPrizeInfo.ACTIVITY_CODE, DOUBLE_DAN)
                                    .eq(ActivityPrizeInfo.LEVEL, 1)
                                    .eq(ActivityPrizeInfo.PRIZE_TYPE, ActivityPrizeInfoTypeConstant.THANK_YOU_FOR_PARTICIPATION)
                                    .eq(ActivityPrizeInfo.STATUS, 1)
                    );
                    activityDoubleDanLotteryVo.setPrizeId(activityPrizeInfo.getId());
                    activityDoubleDanLotteryVo.setPrizeName(activityPrizeInfo.getPrizeName());
                    activityDoubleDanLotteryVo.setPrizeType(activityPrizeInfo.getPrizeType());
                    activityDoubleDanLotteryVo.setPrizeImageReturnUrl(activityPrizeInfo.getPrizeImageReturnUrl());
                    activityDoubleDanLotteryVo.setPrizePrice(activityPrizeInfo.getPrizePrice());
                    activityDoubleDanLotteryVo.setEndTime(activityPrizeInfo.getEndTime());
                }
            }
        } else {
            activityDoubleDanLotteryVo.setEnable(false);
            activityDoubleDanLotteryVo.setRemainingTimes(lotteryCount);
        }
        //统计抽奖次数
        try {
            statisticIncrement(new ActivityDoubleDanStatisticIncrementParam().setKey("RT"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return activityDoubleDanLotteryVo;
    }

    //第一次抽奖概率
    private static final WeightRandom<Integer> lotteryFistWeightRandom = new WeightRandom<>(
            new WeightRandom.WeightObj[]{
                    new WeightRandom.WeightObj<>(10, 35.00),
                    new WeightRandom.WeightObj<>(20, 15.00),
                    new WeightRandom.WeightObj<>(30, 5.00),
                    new WeightRandom.WeightObj<>(40, 5.00),
                    new WeightRandom.WeightObj<>(50, 5.00),
                    new WeightRandom.WeightObj<>(60, 5.00),
                    new WeightRandom.WeightObj<>(70, 5.00),
                    new WeightRandom.WeightObj<>(80, 5.00),
                    new WeightRandom.WeightObj<>(90, 4.00),
                    new WeightRandom.WeightObj<>(100, 2.00),
                    new WeightRandom.WeightObj<>(110, 2.00),
                    new WeightRandom.WeightObj<>(120, 2.00),
                    new WeightRandom.WeightObj<>(130, 2.00),
                    new WeightRandom.WeightObj<>(140, 2.00),
                    new WeightRandom.WeightObj<>(150, 1.00),
                    new WeightRandom.WeightObj<>(160, 1.00),
                    new WeightRandom.WeightObj<>(170, 1.00),
                    new WeightRandom.WeightObj<>(180, 1.00),
                    new WeightRandom.WeightObj<>(190, 1.00),
                    new WeightRandom.WeightObj<>(200, 1.00),
                    new WeightRandom.WeightObj<>(500, 2.00),
                    new WeightRandom.WeightObj<>(1000, 0.50)
            }
    );

    private static final String lotteryFistCount500 = RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_FISTCOUNT + ":500";
    private static final String lotteryFistCount1000 = RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_FISTCOUNT + ":1000";

    //第一次抽奖
    private void lotteryFist(ActivityDoubleDanLotteryParam param, ActivityDoubleDanLotteryVo activityDoubleDanLotteryVo) {
        Integer amount;
        while (true) {
            //抽奖
            amount = lotteryFistWeightRandom.next();
            //限定5,10红包数量
            if (amount == 500) {
                Long increment = redisTemplate.opsForValue().increment(lotteryFistCount500);
                if (increment > 600) {
                    continue;
                }
            } else if (amount == 1000) {
                Long increment = redisTemplate.opsForValue().increment(lotteryFistCount1000);
                if (increment > 200) {
                    continue;
                }
            }
            break;
        }
        //发放红包
        activityBaseService.sendRedEnvelope(amount, DOUBLE_DAN, param.getUserId());
        //拼装返回值
        ActivityPrizeInfo activityPrizeInfo = activityPrizeInfoService.getOne(
                new QueryWrapper<ActivityPrizeInfo>()
                        .eq(ActivityPrizeInfo.ACTIVITY_CODE, DOUBLE_DAN)
                        .eq(ActivityPrizeInfo.LEVEL, 1)
                        .eq(ActivityPrizeInfo.PRIZE_TYPE, ActivityPrizeInfoTypeConstant.RED_ENVELOPE)
                        .eq(ActivityPrizeInfo.STATUS, 1)
                        .last("limit 1")
        );
        activityDoubleDanLotteryVo.setPrizeId(activityPrizeInfo.getId());
        activityDoubleDanLotteryVo.setPrizeName(activityPrizeInfo.getPrizeName());
        activityDoubleDanLotteryVo.setPrizeType(activityPrizeInfo.getPrizeType());
        activityDoubleDanLotteryVo.setPrizeImageReturnUrl(activityPrizeInfo.getPrizeImageReturnUrl());
        activityDoubleDanLotteryVo.setPrizePrice(amount);
        activityDoubleDanLotteryVo.setEndTime(activityPrizeInfo.getEndTime());
    }

    //获取抽奖次数
    private Integer getLotteryCount(Integer userId) {
        HashOperations<String, String, Integer> hashOperations = redisTemplate.opsForHash();
        //获取今天已抽的次数
        Integer numberOfDraws = Convert.toInt(hashOperations.get(getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_COUNT), String.valueOf(userId)), 0);
        if (Objects.isNull(numberOfDraws)) {
            numberOfDraws = 0;
        }
        //获取今天额外的次数
        Integer extraTimes1 = Convert.toInt(hashOperations.get(getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_ALLOW1), String.valueOf(userId)), 0);
        if (Objects.isNull(extraTimes1)) {
            extraTimes1 = 0;
        }
        Integer extraTimes2 = Convert.toInt(hashOperations.get(getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_ALLOW2), String.valueOf(userId)), 0);
        if (Objects.isNull(extraTimes2)) {
            extraTimes2 = 0;
        }
        //剩余次数
        Integer remainingTimes = extraTimes1 + extraTimes2 + 1 - numberOfDraws;
        if (remainingTimes < 0) {
            remainingTimes = 0;
        }
        return remainingTimes;
    }

    //增加抽奖次数
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inrLotteryCount(Integer userId, Integer type) {
        if (Objects.nonNull(userId) && Objects.nonNull(type)) {
            String activityKey;
            switch (type) {
                case 1:
                    activityKey = getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_ALLOW1);
                    break;
                case 2:
                    activityKey = getActivityKey(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_LOTTERY_ALLOW2);
                    break;
                default:
                    activityKey = null;
                    break;
            }
            if (StrUtil.isNotBlank(activityKey)) {
                return redisUtil.runWithLock(activityKey + ":" + userId, () -> {
                    HashOperations<String, String, Integer> hashOperations = redisTemplate.opsForHash();
                    //获取今天额外的次数
                    Integer extraTimes = Convert.toInt(hashOperations.get(activityKey, String.valueOf(userId)), 0);
                    if (Objects.isNull(extraTimes)) {
                        extraTimes = 0;
                    }
                    if (extraTimes < 2) {
                        hashOperations.increment(activityKey, String.valueOf(userId), 1);
                        return true;
                    }
                    return false;
                });
            }
        }
        return false;
    }

    private static String getActivityKey(String endKey) {
        return RedisKeyPreConstant.STATISTICAL_DATA_PRE + RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY + endKey;
    }

    //获取奖品明细
    @Override
    public List<ActivityDrawRecordNew> getAwardDetails(Integer userId) {
        return activityBaseService.getAwardDetails(DOUBLE_DAN, userId);
    }

    /**
     * 活动总统计
     *
     * @return
     */
    @Override
    public ActivityStatTotalResult statTotal() {
        ActivityStatTotalResult result = new ActivityStatTotalResult();
        //新用户数
        result.setNewUserCount(userInviteRelationService.getNewUserCount(4));
        //抽奖人数
        result.setLotteryUserCount(activityUserJoinRecordService.lotteryUserCount(DOUBLE_DAN));
        //抽奖次数
        result.setLotteryCount(statisticBaseService.statisticCount(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, "RT"));
        //节点红包领取人数
        result.setRedGetCount(activityNodeUserRecordService.getRedGetCount(DOUBLE_DAN));
        //活动下单人数
        DoubleDanConfig doubleDanConfig = configService.getDoubleDanConfig();
        doubleDanConfig.setActivityCode(DOUBLE_DAN);
        result.setOrderCount(activityUserJoinRecordService.orderCount(doubleDanConfig));
        return result;
    }

    /**
     * 各节点红包领取统计
     *
     * @return
     */
    @Override
    public List<ActivityStatRedResult> redTotal() {
        return activityNodeUserRecordService.redTotal(DOUBLE_DAN);
    }

    /**
     * 活动点击量统计
     *
     * @return
     */
    @Override
    public List<ActivityStatClickResult> clickTotal() {
        List<ActivityStatClickResult> results = Lists.newArrayList();
        //客户端
        Integer appAtc = statisticBaseService.statisticCount(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, "ATC");
        results.add(new ActivityStatClickResult(appAtc, 1));
        //h5
        Integer h5Atc = statisticBaseService.statisticCount(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, "ACA");
        results.add(new ActivityStatClickResult(h5Atc, 2));
        return results;
    }

    /**
     * 活动转发人数统计
     *
     * @return
     */
    @Override
    public List<ActivityStatForwardUserResult> forwardUserTotal() {
        return activityNodeUserRecordService.forwardUserTotal(DOUBLE_DAN_AFNR);
    }

    /**
     * 活动转发次数统计
     *
     * @return
     */
    @Override
    public List<ActivityStatForwardTimeResult> forwardTimeTotal() {
        List<ActivityStatForwardTimeResult> results = Lists.newArrayList();
        //客户端
        Integer appAtc = statisticBaseService.statisticCount(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, "AFC");
        results.add(new ActivityStatForwardTimeResult(appAtc, 1));
        //h5
        Integer h5Atc = statisticBaseService.statisticCount(RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY, RedisKeyPreConstant.STATISTICAL_DATA_MIDDLE_ACTIVITY_END_DOUBLEDAN_COUNT, "ARA");
        results.add(new ActivityStatForwardTimeResult(h5Atc, 2));
        return results;
    }
}
